local sk__xinghan = fk.CreateSkill {

  name = "sk__xinghan",

  tags = {},

}

local sk__xinghan_ban_list = {
  "zuoci", "ol_ex__zuoci", "js__xushao", "shichangshi", "sk__zuoci"
}

sk__xinghan:addEffect(fk.GameStart, {
  anim_type = "special",
  can_trigger = function(self, event, target, player, data)
    return player:hasSkill(sk__xinghan.name)
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local all_kingdoms, generals = {}, {}
    for _, general in ipairs(room.general_pile) do
      if not table.contains(sk__xinghan_ban_list, general) and
          not table.contains(player:getTableMark("sk__xinghan_selected"), general) and
          not Fk.generals[general].subkingdom then
        local kingdom = Fk.generals[general].kingdom
        table.insertIfNeed(all_kingdoms, kingdom)
        generals[kingdom] = generals[kingdom] or {}
        table.insert(generals[kingdom], general)
      end
    end
    local kingdoms = table.filter(all_kingdoms, function(kingdom)
      return not table.contains(player:getTableMark("sk__xinghan_invalid_kingdoms"), kingdom)
    end)
    if #player:getTableMark("@&sk__xinghan") == 3 then
      kingdoms = table.filter(kingdoms, function(kingdom)
        return table.find(player:getTableMark("@&sk__xinghan"), function(general)
          return Fk.generals[general].kingdom == kingdom
        end)
      end)
    end
    if #kingdoms == 0 then return end
    local choices, all_choices = {}, {}
    for _, kingdom in ipairs({ "wei", "shu", "wu", "qun", "jin", "god" }) do
      if table.contains(all_kingdoms, kingdom) then
        table.insert(all_choices, kingdom)
      end
      if table.contains(kingdoms, kingdom) then
        table.insert(choices, kingdom)
      end
    end
    for _, kingdom in ipairs(all_kingdoms) do
      table.insertIfNeed(all_choices, kingdom)
    end
    for _, kingdom in ipairs(kingdoms) do
      table.insertIfNeed(choices, kingdom)
    end
    local choice = room:askForChoice(player, choices, sk__xinghan.name, "#sk__xinghan-kingdom", false, all_choices)
    local general_choices = table.random(generals[choice], 3)
    local general_skills = {}
    for _, general in ipairs(general_choices) do
      table.insert(general_skills, Fk.generals[general]:getSkillNameList())
    end
    local result = room:askForCustomDialog(
      player, sk__xinghan.name,
      "packages/utility/qml/ChooseSkillFromGeneralBox.qml",
      { general_choices, general_skills, "#sk__xinghan-general" }
    )
    if result == "" then
      result = { general_choices[1] }
    end
    local general, _ = table.unpack(result)
    room:addTableMark(player, "sk__xinghan_selected", general)
    local mark = player:getTableMark("@&sk__xinghan")
    if #mark > 0 then
      for i = 1, #mark, 1 do
        local g = mark[i]
        if Fk.generals[general].kingdom == Fk.generals[g].kingdom then
          if room:askForSkillInvoke(player, sk__xinghan.name, nil, "#sk__xinghan-change:::" .. g .. ":" .. general) then
            table.removeOne(room.general_pile, general)
            room:returnToGeneralPile(Fk.generals[g])
            mark[i] = general
            room:setPlayerMark(player, "@&sk__xinghan", mark)
          end
          return
        end
      end
    end
    table.removeOne(room.general_pile, general)
    room:addTableMark(player, "@&sk__xinghan", general)
    room:addTableMark(player, "sk__xinghan_hp", Fk.generals[general].hp)
  end,
})
sk__xinghan:addEffect(fk.TurnStart, {
  anim_type = "special",
  can_trigger = function(self, event, target, player, data)
    return player:hasSkill(sk__xinghan.name) and target == player
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local all_kingdoms, generals = {}, {}
    for _, general in ipairs(room.general_pile) do
      if not table.contains(sk__xinghan_ban_list, general) and
          not table.contains(player:getTableMark("sk__xinghan_selected"), general) and
          not Fk.generals[general].subkingdom then
        local kingdom = Fk.generals[general].kingdom
        table.insertIfNeed(all_kingdoms, kingdom)
        generals[kingdom] = generals[kingdom] or {}
        table.insert(generals[kingdom], general)
      end
    end
    local kingdoms = table.filter(all_kingdoms, function(kingdom)
      return not table.contains(player:getTableMark("sk__xinghan_invalid_kingdoms"), kingdom)
    end)
    if #player:getTableMark("@&sk__xinghan") == 3 then
      kingdoms = table.filter(kingdoms, function(kingdom)
        return table.find(player:getTableMark("@&sk__xinghan"), function(general)
          return Fk.generals[general].kingdom == kingdom
        end)
      end)
    end
    if #kingdoms == 0 then return end
    local choices, all_choices = {}, {}
    for _, kingdom in ipairs({ "wei", "shu", "wu", "qun", "jin", "god" }) do
      if table.contains(all_kingdoms, kingdom) then
        table.insert(all_choices, kingdom)
      end
      if table.contains(kingdoms, kingdom) then
        table.insert(choices, kingdom)
      end
    end
    for _, kingdom in ipairs(all_kingdoms) do
      table.insertIfNeed(all_choices, kingdom)
    end
    for _, kingdom in ipairs(kingdoms) do
      table.insertIfNeed(choices, kingdom)
    end
    local choice = room:askForChoice(player, choices, sk__xinghan.name, "#sk__xinghan-kingdom", false, all_choices)
    local general_choices = table.random(generals[choice], 3)
    local general_skills = {}
    for _, general in ipairs(general_choices) do
      table.insert(general_skills, Fk.generals[general]:getSkillNameList())
    end
    local result = room:askForCustomDialog(
      player, sk__xinghan.name,
      "packages/utility/qml/ChooseSkillFromGeneralBox.qml",
      { general_choices, general_skills, "#sk__xinghan-general" }
    )
    if result == "" then
      result = { general_choices[1] }
    end
    local general, _ = table.unpack(result)
    room:addTableMark(player, "sk__xinghan_selected", general)
    local mark = player:getTableMark("@&sk__xinghan")
    if #mark > 0 then
      for i = 1, #mark, 1 do
        local g = mark[i]
        if Fk.generals[general].kingdom == Fk.generals[g].kingdom then
          if room:askForSkillInvoke(player, sk__xinghan.name, nil, "#sk__xinghan-change:::" .. g .. ":" .. general) then
            table.removeOne(room.general_pile, general)
            room:returnToGeneralPile(Fk.generals[g])
            mark[i] = general
            room:setPlayerMark(player, "@&sk__xinghan", mark)
          end
          return
        end
      end
    end
    table.removeOne(room.general_pile, general)
    room:addTableMark(player, "@&sk__xinghan", general)
    room:addTableMark(player, "sk__xinghan_hp", Fk.generals[general].hp)
  end,
})

sk__xinghan:addEffect(fk.TurnEnd, {
  anim_type = "special",
  can_trigger = function(self, event, target, player, data)
    if target == player and player:getMark("@&sk__xinghan") ~= 0 then
      return not player:insideExtraTurn()
    end
  end,
  on_cost = Util.TrueFunc,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local isDeputy = player.deputyGeneral == "sk__wanniangongzhu"
    if isDeputy then
      room:setPlayerMark(player, "sk__xinghan_orig", { player.deputyGeneral, 2, player.hp })
    else
      room:setPlayerMark(player, "sk__xinghan_orig", { player.general, 1, player.hp })
    end
    for i = 1, 3, 1 do
      if player.dead then return end
      if #player:getTableMark("@&sk__xinghan") < i then
        break
      end
      for _, p in ipairs(room.players) do
        p:setCardUseHistory("", 0, Player.HistoryTurn)
        p:setSkillUseHistory("", 0, Player.HistoryTurn)
        for name, _ in pairs(p.mark) do
          if name:find("-turn", 1, true) then
            room:setPlayerMark(p, name, 0)
          end
        end
      end
      for cid, cmark in pairs(room.card_marks) do
        for name, _ in pairs(cmark) do
          if name:find("-turn", 1, true) then
            room:setCardMark(Fk:getCardById(cid), name, 0)
          end
        end
      end
      for _, p in ipairs(room.players) do
        p:filterHandcards()
        room:broadcastProperty(p, "MaxCards")
      end
      if player:getMark("sk__xinghan_hp")[i] > 0 then
        room:setPlayerMark(player, "sk__xinghan_status", i)
        local general = player:getMark("@&sk__xinghan")[i]
        room:changeHero(player, general, false, isDeputy, true, true, true)
        if player.dead then return end
        room:setPlayerProperty(player, "hp", math.min(player:getMark("sk__xinghan_hp")[i], player.maxHp))
        if player.dead then return end
        player:gainAnExtraTurn(false, sk__xinghan.name)
        if player.dead then return end
        local mark = player:getMark("sk__xinghan_hp")
        mark[i] = player.hp
        room:setPlayerMark(player, "sk__xinghan_hp", mark)
      end
    end
    if not player.dead then
      local choices = { player:getMark("sk__xinghan_orig")[1] }
      for i = 1, 3, 1 do
        if #player:getTableMark("@&sk__xinghan") < i then
          break
        end
        if player:getMark("sk__xinghan_hp")[i] > 0 then
          table.insert(choices, player:getMark("@&sk__xinghan")[i])
        end
      end
      if #choices == 1 then return end
      local skills = {}
      for _, general in ipairs(choices) do
        table.insert(skills, Fk.generals[general]:getSkillNameList())
      end
      local result = room:askForCustomDialog(
        player, sk__xinghan.name,
        "packages/utility/qml/ChooseSkillFromGeneralBox.qml",
        { choices, skills, "#sk__xinghan-changeHero" }
      )
      if result == "" then
        result = { choices[1] }
      end
      local general, _ = table.unpack(result)
      if isDeputy and general ~= player.deputyGeneral or general ~= player.general then
        local mark = player:getMark("sk__xinghan_hp")
        mark[player:getMark("sk__xinghan_status")] = player.hp
        room:setPlayerMark(player, "sk__xinghan_hp", mark)
        if general == player:getMark("sk__xinghan_orig")[1] then
          room:setPlayerMark(player, "sk__xinghan_status", 0)
          room:changeHero(player, general, false, isDeputy, true, true, true)
          if player.dead then return end
          room:setPlayerProperty(player, "hp", math.min(player:getMark("sk__xinghan_orig")[3], player.maxHp))
          room:setPlayerMark(player, "sk__xinghan_orig", 0)
        else
          local status = table.indexOf(player:getMark("@&sk__xinghan"), general)
          room:setPlayerMark(player, "sk__xinghan_status", status)
          room:changeHero(player, general, false, isDeputy, true, true, true)
          if player.dead then return end
          room:setPlayerProperty(player, "hp", math.min(player:getMark("sk__xinghan_hp")[status], player.maxHp))
        end
      end
    end
  end,
})
sk__xinghan:addEffect(fk.AskForPeachesDone, {
  anim_type = "special",
  can_trigger = function(self, event, target, player, data)
    if target == player and player:getMark("@&sk__xinghan") ~= 0 then
      return player:getMark("sk__xinghan_status") > 0
    end
  end,
  on_cost = Util.TrueFunc,
  on_use = function(self, event, target, player, data)
    local room = player.room
    room:addTableMark(player, "sk__xinghan_invalid_kingdoms",
      Fk.generals[player:getMark("@&sk__xinghan")[player:getMark("sk__xinghan_status")]].kingdom)
    local mark = player:getMark("sk__xinghan_hp")
    mark[player:getMark("sk__xinghan_status")] = player.hp
    room:setPlayerMark(player, "sk__xinghan_hp", mark)
    if player:getMark("sk__xinghan_status") < #player:getMark("@&sk__xinghan") then
      for i = player:getMark("sk__xinghan_status"), #player:getMark("@&sk__xinghan"), 1 do
        if player:getMark("sk__xinghan_hp")[i] > 0 then
          room:setPlayerMark(player, "sk__xinghan_status", i)
          local general = player:getMark("@&sk__xinghan")[i]
          local isDeputy = player:getMark("sk__xinghan_orig")[2] == 2
          room:changeHero(player, general, false, isDeputy, true, true, true)
          if player.dead then return end
          room:setPlayerProperty(player, "hp", math.min(player:getMark("sk__xinghan_hp")[i], player.maxHp))
          return
        end
      end
    end
    room:setPlayerMark(player, "sk__xinghan_status", 0)
    local isDeputy = player:getMark("sk__xinghan_orig")[2] == 2
    room:changeHero(player, player:getMark("sk__xinghan_orig")[1], false, isDeputy, true, true, true)
    if player.dead then return end
    room:setPlayerProperty(player, "hp", math.min(player:getMark("sk__xinghan_orig")[3], player.maxHp))
    room:setPlayerMark(player, "sk__xinghan_orig", 0)
  end,
})
sk__xinghan:addEffect(fk.BeforeTurnStart, {
  can_refresh = function(self, event, target, player, data)
    return target == player and player:getMark("@&sk__xinghan") ~= 0 and not player:insideExtraTurn() and
        player:getMark("sk__xinghan_status") > 0 and player:getMark("sk__xinghan_orig") ~= 0
  end,
  on_refresh = function(self, event, target, player, data)
    local room = player.room
    local mark = player:getMark("sk__xinghan_hp")
    mark[player:getMark("sk__xinghan_status")] = player.hp
    room:setPlayerMark(player, "sk__xinghan_hp", mark)
    room:setPlayerMark(player, "sk__xinghan_status", 0)
    local isDeputy = player:getMark("sk__xinghan_orig")[2] == 2
    room:changeHero(player, player:getMark("sk__xinghan_orig")[1], false, isDeputy, true, true, true)
    if player.dead then return end
    room:setPlayerProperty(player, "hp", math.min(player:getMark("sk__xinghan_orig")[3], player.maxHp))
    room:setPlayerMark(player, "sk__xinghan_orig", 0)
  end,
})

return sk__xinghan
